<!DOCTYPE html>
<html>
<head>
  <script src="../../processing.js"></script>
<link rel="stylesheet" href="../style.css"/></head>
<body><h1><a href="http://ejohn.org/blog/processingjs/">Processing.js</a></h1>
<h2>Puff</h2>

<p>by Ira Greenberg.  

Series of ellipses simulating a multi-segmented 
organism, utilizing a follow the leader algorithm.
Collision detection occurs on the organism's head, 
controlling overall direction, and on the individual 
body segments, controlling body shape and jitter.</p>

<p><a href="http://processing.org/learning/topics/puff.html"><b>Original Processing.org Example:</b> Puff</a><br>
<script type="application/processing">
// for puff head
float headX;
float headY;
float speedX = .7;
float speedY = .9;

// for puff body
int cells = 1000;
float[]px= new float[cells];
float[]py= new float[cells];
float[]radiiX = new float[cells];
float[]radiiY = new float[cells];
float[]angle = new float[cells];
float[]frequency = new float[cells];
float[]cellRadius = new float[cells];

void setup(){
  
  size(200, 200);
  // begin in the center
  headX = width/2;
  headY = height/2;

  //fill body arrays
  for (int i=0; i< cells; i++){
    radiiX[i] = random(-7, 7); 
    radiiY[i] = random(-4, 4);
    frequency[i]= random(-9, 9);
    cellRadius[i] = random(16, 30);
  }
  frameRate(30);
}

void draw(){
  background(0);
  noStroke();
  fill(255, 255, 255, 5);

  //follow the leader
  for (int i =0; i< cells; i++){
    if (i==0){
      px[i] = headX+sin(radians(angle[i]))*radiiX[i];
      py[i] = headY+cos(radians(angle[i]))*radiiY[i];
    } 
    else{
      px[i] = px[i-1]+cos(radians(angle[i]))*radiiX[i];
      py[i] = py[i-1]+sin(radians(angle[i]))*radiiY[i];

      //check collision of body
      if (px[i] >= width-cellRadius[i]/2 || px[i] <= cellRadius[i]/2){
        radiiX[i]*=-1;
        cellRadius[i] = random(1, 40);
        frequency[i]= random(-13, 13);
      }
      if (py[i] >= height-cellRadius[i]/2 || py[i] <= cellRadius[i]/2){
        radiiY[i]*=-1;
        cellRadius[i] = random(1, 40);
        frequency[i]= random(-9, 9);
      }
    }
    // draw puff
    ellipse(px[i],  py[i],  cellRadius[i],  cellRadius[i]);
    // set speed of body
    angle[i]+=frequency[i];
  }

  // set velocity of head
  headX+=speedX;
  headY+=speedY;

  //check boundary collision of head
  if (headX >= width-cellRadius[0]/2 || headX <=cellRadius[0]/2){
    speedX*=-1;
  }
  if (headY >= height-cellRadius[0]/2 || headY <= cellRadius[0]/2){
    speedY*=-1;
  }
}
</script><canvas width="200" height="200"></canvas></p>
<div style="height:0px;width:0px;overflow:hidden;"></div>

<pre><b>// All Examples Written by <a href="http://reas.com/">Casey Reas</a> and <a href="http://benfry.com/">Ben Fry</a>
// unless otherwise stated.</b>
// for puff head
float headX;
float headY;
float speedX = .7;
float speedY = .9;

// for puff body
int cells = 1000;
float[]px= new float[cells];
float[]py= new float[cells];
float[]radiiX = new float[cells];
float[]radiiY = new float[cells];
float[]angle = new float[cells];
float[]frequency = new float[cells];
float[]cellRadius = new float[cells];

void setup(){
  
  size(200, 200);
  // begin in the center
  headX = width/2;
  headY = height/2;

  //fill body arrays
  for (int i=0; i&lt; cells; i++){
    radiiX[i] = random(-7, 7); 
    radiiY[i] = random(-4, 4);
    frequency[i]= random(-9, 9);
    cellRadius[i] = random(16, 30);
  }
  frameRate(30);
}

void draw(){
  background(0);
  noStroke();
  fill(255, 255, 255, 5);

  //follow the leader
  for (int i =0; i&lt; cells; i++){
    if (i==0){
      px[i] = headX+sin(radians(angle[i]))*radiiX[i];
      py[i] = headY+cos(radians(angle[i]))*radiiY[i];
    } 
    else{
      px[i] = px[i-1]+cos(radians(angle[i]))*radiiX[i];
      py[i] = py[i-1]+sin(radians(angle[i]))*radiiY[i];

      //check collision of body
      if (px[i] &gt;= width-cellRadius[i]/2 || px[i] &lt;= cellRadius[i]/2){
        radiiX[i]*=-1;
        cellRadius[i] = random(1, 40);
        frequency[i]= random(-13, 13);
      }
      if (py[i] &gt;= height-cellRadius[i]/2 || py[i] &lt;= cellRadius[i]/2){
        radiiY[i]*=-1;
        cellRadius[i] = random(1, 40);
        frequency[i]= random(-9, 9);
      }
    }
    // draw puff
    ellipse(px[i],  py[i],  cellRadius[i],  cellRadius[i]);
    // set speed of body
    angle[i]+=frequency[i];
  }

  // set velocity of head
  headX+=speedX;
  headY+=speedY;

  //check boundary collision of head
  if (headX &gt;= width-cellRadius[0]/2 || headX &lt;=cellRadius[0]/2){
    speedX*=-1;
  }
  if (headY &gt;= height-cellRadius[0]/2 || headY &lt;= cellRadius[0]/2){
    speedY*=-1;
  }
}</pre>
</body>
</html>
